package com.wxj.bank.module.utils;

import com.wxj.bank.module.enums.ExcelType;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @author shengtao
 * @Description: excel导出工具
 * @date 2019/01/30 10:51
 */
public class ExcelUtils {

    /**
     * 导出excel文件
     *
     * @param ts 导出的数据集合
     * @param filterFields 过滤的数据字段名集合
     * @param clazz Class<T>
     * @param headers 第一行头标题
     * @param excelType excel类型.xls,.xlsx
     * @param outputStream 输出流
     * @param <T>
     * @throws Exception
     */
    public static <T> void exportExcel(List<T> ts, List<String> filterFields, Class<T> clazz, List<String> headers, ExcelType excelType, OutputStream outputStream) throws Exception{
        if (null == ts || null == headers) {
            throw new RuntimeException("导出excel数据集或头标题为空");
        }
        if (null == outputStream){
            throw new RuntimeException("导出excel输出流不能为空");
        }
        //在内存中创建一个excel文件
        Workbook workbook = null;
        if(excelType == ExcelType.POI_EXCEL_XLS){
            workbook = new HSSFWorkbook();
        }else if(excelType == ExcelType.POI_EXCEL_XLSX){
            workbook = new XSSFWorkbook();
        }else {
            throw new RuntimeException("不支持的导出文件类型");
        }
        exportXLSXExcel(workbook,ts,filterFields,clazz,headers,outputStream);
    }


    private static <T> void exportXLSXExcel(Workbook workbook,List<T> ts, List<String> filterFields, Class<T> clazz, List<String> headers, OutputStream outputStream) throws Exception {
        //创建工作簿
        Sheet sheet = workbook.createSheet();
        sheet.setDefaultRowHeightInPoints(20);// 设置缺省列高
        sheet.setDefaultColumnWidth(15);
        //创建标题行
        Row row0 = sheet.createRow(0);
        /**
         * 设置头样式
         */
        CellStyle headStyle = workbook.createCellStyle();
        headStyle.setAlignment(HorizontalAlignment.CENTER);
        headStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        Font headFont = workbook.createFont();
        headFont.setBold(true);
        headFont.setColor(Font.COLOR_NORMAL);
        headFont.setFontName("宋体");
        headStyle.setFont(headFont);
        row0.setRowStyle(headStyle);
        int i = 0;
        for (String title : headers) {
            Cell cell = row0.createCell(i);
            cell.setCellStyle(headStyle);
            cell.setCellValue(title);
            i++;
        }

        /**
         * 设置数据样式
         */
        CellStyle bodyStyle = workbook.createCellStyle();
        bodyStyle.setAlignment(HorizontalAlignment.CENTER);
        bodyStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        Font bodyFont = workbook.createFont();
        bodyFont.setColor(Font.COLOR_NORMAL);
        bodyFont.setFontName("宋体");
        bodyStyle.setFont(bodyFont);

        //生成数据
        i = 1;
        for (T t : ts) {
            Row row = sheet.createRow(i++);
            String textValue = null;
            //便利父类，获取field
            List<Field> fields = getFields(clazz);
            int j = 0;
            for (Field field : fields) {
                if (null != filterFields && filterFields.contains(field.getName())) {
                    continue;
                }
                Cell cell = row.createCell(j);
                cell.setCellStyle(bodyStyle);
                String fieldName = field.getName();
                String getMethod = "get" + fieldName.substring(0, 1).toUpperCase()
                        + fieldName.substring(1);
                Method method = null;
                method = clazz.getMethod(getMethod, new Class[]{});
                Object value = method.invoke(t, new Object[]{});
                if (value instanceof Date) {
                    textValue = DateUtils.dateToString((Date) value, DateUtils.DEFAULT_DATETIME_PATTERN);
                } else {
                    // 其它数据类型都当作字符串简单处理
                    textValue = value.toString();
                }
                cell.setCellValue(textValue);
                j++;
            }
        }
        try {
            workbook.write(outputStream);
        } catch (IOException e) {
            throw new RuntimeException("excel输出异常");
        } finally {
            workbook.close();
        }
    }

    private static <T> List<Field> getFields(Class<T> clazz) {
        //获取属性
        Class clazz1 = clazz.getSuperclass();
        List<Field> fields = new ArrayList<>();
        if (null != clazz1) {
            Field[] field1 = clazz1.getDeclaredFields();
            fields.addAll(Arrays.asList(field1));
        }
        Field[] field2 = clazz.getDeclaredFields();
        fields.addAll(Arrays.asList(field2));
        return fields;
    }

}
